
#include "PkgQueue.h"
#include "cc_pub.h"

/********* interior	define ***********/
#define CFG_RWLOCK_CHECK 

#define LLOG
#define LLOG_ERR
#define LLOG_MARK
#include "llog.h"

#ifdef	CFG_STATIC_BUF_ALLOCATE
#define L_MALLOC 	SMalloc
#define L_FREE(A) 	LLOG_ERR()
#else
#define L_MALLOC 	malloc
#define L_FREE(A)	free(A)
#endif

/********* interior  struct **********/
struct CC_Data_Packet_Queue_V4{
    uint8_t* pBuf;
	uint32_t BufSz;	// IndexMax

	uint32_t wIndex;         
    uint32_t rIndex;
	
	uint8_t  RWLock;
	
	uint32_t recvNum; //统计接受包数量
};

/********** global val ***************/

/******* local function **************/

/******* TODO ************************/

/* 设计说明
	1- PkgQueue 数据帧格式： 
		A: u16Len+Data[u16Len&0x7FFF]
		B: u8Len+Data[u16Len&0x7F]
	2- 首字节最高bit ==1 使用 格式A 否则使用格式B
	3- 嵌入式协议中 多数时命令数据包，而命令数据包多数小于128
	4- 实际使用中 单包长度 不应该 大于 0x7FFF;应该远远效与此值;
	5- 为简化实现，写入数据包超长则丢弃，不能截断存储；
	
*/

//=============
#ifdef CFG_PKG_QUEUE
void PkgQueue_ShowObj(tPkgQueue* pObj){
    LLOG("PkgQueue\n");
	LLOG("pBuf	 =[%x]\n",pObj->pBuf	);
	LLOG("BufSz	 =[%d]\n",pObj->BufSz	);
	LLOG("wIndex =[%d]\n",pObj->wIndex	);
	LLOG("rIndex =[%d]\n",pObj->rIndex	);
	LLOG("RWLock =[%x]\n",pObj->RWLock	);
	
	LLOG("RecvNum =[%d]\n",pObj->recvNum);
}

int PkgQueue_Init(tPkgQueue* pObj ,uint32_t BufSz, uint8_t* pBuf){ 
    
	int ret = RET_ERR;
    int i;
	uint8_t* ptmp;
	
	if(pObj == NULL || pBuf == NULL || BufSz == 0){
		LLOG_ERR();
		return ret;
	}
	ret = RET_OK;
	
	ptmp=(uint8_t*)pObj;
	for(i=0;i<sizeof(tPkgQueue);i++){
		ptmp[i]=0;
	}
	pObj->pBuf 	= pBuf;
	pObj->BufSz = BufSz; 
	
    return ret;   
}

tPkgQueue* PkgQueue_Create(uint32_t BufSz){
	
	tPkgQueue* ptmp=NULL;
	uint8_t* 	pBuf=NULL;
	
	if(BufSz == 0){
		return ptmp;
	}
	
	ptmp=(tPkgQueue*)L_MALLOC(sizeof(tPkgQueue));
	if(ptmp == NULL){
		LLOG_ERR();
		return ptmp;
	}
	pBuf=L_MALLOC(BufSz);
	if(pBuf == NULL){
		L_FREE(ptmp);
		LLOG_ERR();
		return NULL;
	}	
	
	PkgQueue_Init(ptmp,BufSz,pBuf);

	return ptmp;
}

uint32_t PkgQueue_Write(tPkgQueue* pObj,uint32_t dLen, uint8_t* pPkg){
	
	uint8_t* pBuf;
	
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t PartNum;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
    uint32_t RealCopyNum;
    
	CopySz=0;
    if( (pObj== NULL) || (pPkg == NULL) || (dLen == 0) ){
        return CopySz;
    }
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){
		return CopySz;
	}
	#endif
	pObj->RWLock=1; // n-API 互斥
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->BufSz;
	
	LOOP_CALC(CopySz,wIndex,rIndex,LoopSz);		 // empty 
	CopySz -= 1;
	//
	pBuf = pObj->pBuf;
	
	if(dLen > 0x7F){
		if(CopySz < dLen+2){
			pObj->RWLock = 0;
			LLOG_MARK();
			return 0;
		}
		// LLOG_MARK();
		LLOG("#I PkgQueue u16Pkg\n");
		pBuf[wIndex++] = (dLen>>8)|0x80;
		wIndex = (wIndex < LoopSz)?wIndex:0;
		pBuf[wIndex++] = dLen&0xFF;
		wIndex = (wIndex < LoopSz)?wIndex:0;
	
	}
	else{
		if(CopySz < dLen+1){ 
			pObj->RWLock = 0;
			LLOG_MARK();
			return 0;
		}
		LLOG("#I PkgQueue u8Pkg\n");
		// LLOG_MARK();
		pBuf[wIndex++] = dLen&0x7F; 
		wIndex = (wIndex < LoopSz)?wIndex:0;		
	}
	

	CopySz=(CopySz > dLen)? dLen: CopySz; 
	if(CopySz ==1){	// 单字节写入加速	
		pBuf[wIndex++] = pPkg[0];
	}
	else{
		
		PartNum= LoopSz-wIndex; 
		if( CopySz > PartNum)
		{
			for(i=0;i<PartNum;i++){
				pBuf[wIndex++]=pPkg[i];
			}
			wIndex = 0;
			for(;i<CopySz;i++){
				pBuf[wIndex++]=pPkg[i];
			}
		}
		else{ 
			for(i=0;i<CopySz;i++){
				pBuf[wIndex++]=pPkg[i];
			}
		}
		
	}
	wIndex = (wIndex < LoopSz)?wIndex:0;
	
	pObj->wIndex = wIndex;
	pObj->recvNum++;
	pObj->RWLock=0;
    return CopySz;
	
}

uint32_t PkgQueue_Read(tPkgQueue* pObj,uint32_t readNum, uint8_t* pRBuf){

	uint8_t* pBuf;
	
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t PartNum;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
	
	uint16_t dLen;
	uint16_t DropLen;
    
	CopySz=0;
    if( (pObj== NULL) || (pRBuf == NULL) || (readNum == 0) ){
        return CopySz;
    }
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){	// n-API 互斥
		return CopySz;
	}
	#endif
	pObj->RWLock=1; 
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->BufSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
    if(CopySz < 2){
		pObj->RWLock = 0;
		return CopySz;
	}
	//
	pBuf = pObj->pBuf;	
	// 读取数据包长度
	dLen = pBuf[rIndex];
	pBuf[rIndex] = 0;
	rIndex++;
	rIndex = (rIndex < LoopSz)?rIndex:0;
	if(dLen&0x80){		
		dLen <<=8;
		dLen += pBuf[rIndex];
		dLen = dLen&0x7FFF;
		pBuf[rIndex] = 0;
		rIndex++;
		rIndex = (rIndex < LoopSz)?rIndex:0;
	}
	//
	CopySz	= (readNum > dLen)? dLen: readNum;
	
	PartNum= LoopSz-rIndex; //  PartNum > 0
	if(CopySz > PartNum){
		for(i=0;i<PartNum;i++){
			pRBuf[i] = pBuf[rIndex];
			pBuf[rIndex++] = 0;
		}
		rIndex = 0; 
		for(;i<CopySz;i++){
			pRBuf[i] = pBuf[rIndex];
			pBuf[rIndex++] = 0;
		}
	}
	else{
		for(i=0;i<CopySz;i++){
			pRBuf[i] = pBuf[rIndex];
			pBuf[rIndex++] = 0;
		}
	}
	rIndex = (rIndex < LoopSz)?rIndex:0;

	// Drop
	if(readNum < dLen){
		DropLen = dLen-readNum;	
		for(i=0;i<DropLen;i++){
			pBuf[rIndex++] = 0;
			rIndex = (rIndex < LoopSz)?rIndex:0;
		}	
	}
	
	pObj->rIndex = rIndex;
	pObj->recvNum--;
	pObj->RWLock = 0;
    return CopySz;
	
}

uint32_t PkgQueue_GetNextPkgSz(tPkgQueue* pObj){

	uint8_t* pBuf;
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t PartNum;
    uint32_t LoopSz;
    uint32_t CopySz;

	uint16_t dLen;
    
	CopySz=0;
    if(pObj == NULL){
        return CopySz;
    }
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){	// n-API 互斥
		return CopySz;
	}
	#endif
	pObj->RWLock=1; 
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->BufSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
    if(CopySz < 2){
		pObj->RWLock = 0;
		return CopySz;
	}

	pBuf = pObj->pBuf;
	// 读取数据包长度
	dLen = pBuf[rIndex];
	rIndex++;
	rIndex = (rIndex < LoopSz)?rIndex:0;
	if(dLen&0x80){		
		dLen <<=8;
		dLen += pBuf[rIndex];
		dLen = dLen&0x7FFF;
		rIndex++;
		rIndex = (rIndex < LoopSz)?rIndex:0;
	}
	return dLen;
}

uint32_t PkgQueue_GetRecvNum(tPkgQueue* pObj){
	uint32_t ret=0;
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){ // n-API 互斥
		return ret;
	}
	#endif
	pObj->RWLock = 1; 	
	ret = pObj->recvNum;
	pObj->RWLock = 0;
	return ret;
}

int PkgQueue_Reset(tPkgQueue* pObj){
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){ // n-API 互斥
		return RET_ERR;
	}
	#endif
	pObj->RWLock = 1; 	
	pObj->wIndex = 0;
	pObj->rIndex = 0;
	
	MEMSET(pObj->pBuf,0,pObj->BufSz);
	
	pObj->RWLock = 0;
	
	return RET_OK;
}

#endif

#ifdef CFG_PKG_QUEUE // 未 测试 

uint32_t PkgQueue_Peek(tPkgQueue* pObj,uint32_t readNum, uint8_t* pRBuf){

	uint8_t* pBuf;
	
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t PartNum;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
	
	uint16_t dLen;
	uint16_t DropLen;
    
	CopySz=0;
    if( (pObj== NULL) || (pRBuf == NULL) || (readNum == 0) ){
        return CopySz;
    }
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){	// n-API 互斥
		return CopySz;
	}
	#endif
	pObj->RWLock=1; 
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->BufSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
    if(CopySz < 2){
		pObj->RWLock = 0;
		return CopySz;
	}
	//
	pBuf = pObj->pBuf;	
	// 读取数据包长度
	dLen = pBuf[rIndex];
	// pBuf[rIndex] = 0;
	rIndex++;
	rIndex = (rIndex < LoopSz)?rIndex:0;
	if(dLen&0x80){		
		dLen <<=8;
		dLen += pBuf[rIndex];
		dLen = dLen&0x7FFF;
		// pBuf[rIndex] = 0;
		rIndex++;
		rIndex = (rIndex < LoopSz)?rIndex:0;
	}
	//
	CopySz	= (readNum > dLen)? dLen: readNum;
	
	PartNum= LoopSz-rIndex; //  PartNum > 0
	if(CopySz > PartNum){
		for(i=0;i<PartNum;i++){
			pRBuf[i] = pBuf[rIndex];
			rIndex++;// pBuf[rIndex++] = 0;
		}
		rIndex = 0; 
		for(;i<CopySz;i++){
			pRBuf[i] = pBuf[rIndex];
			rIndex++;// pBuf[rIndex++] = 0;
		}
	}
	else{
		for(i=0;i<CopySz;i++){
			pRBuf[i] = pBuf[rIndex];
			rIndex++;// pBuf[rIndex++] = 0;
		}
	}
	rIndex = (rIndex < LoopSz)?rIndex:0;

	// Drop
	if(readNum < dLen){
		DropLen = dLen-readNum;	
		for(i=0;i<DropLen;i++){
			rIndex++;// pBuf[rIndex++] = 0;
			rIndex = (rIndex < LoopSz)?rIndex:0;
		}	
	}
	
	// pObj->rIndex = rIndex;
	// pObj->recvNum--;
	pObj->RWLock = 0;
    return CopySz;
	
}

uint32_t PkgQueue_DropOne(tPkgQueue* pObj){

	uint8_t* pBuf;
	
    uint32_t rIndex;
    uint32_t wIndex;
    uint32_t PartNum;
    uint32_t LoopSz;

    uint32_t i;
    uint32_t CopySz;
	
	uint16_t dLen;
	uint16_t DropLen;
    
	CopySz=0;
    if( pObj== NULL){
        return CopySz;
    }
	
	#ifdef CFG_RWLOCK_CHECK
	if(pObj->RWLock != 0){	// n-API 互斥
		return CopySz;
	}
	#endif
	pObj->RWLock=1; 
	
	wIndex = pObj->wIndex;
	rIndex = pObj->rIndex;
	LoopSz = pObj->BufSz;
	
	LOOP_CALC_ZERO(CopySz,rIndex,wIndex,LoopSz);		 // RecvNum 
	
    if(CopySz < 2){
		pObj->RWLock = 0;
		return CopySz;
	}
	//
	pBuf = pObj->pBuf;	
	// 读取数据包长度
	dLen = pBuf[rIndex];
	pBuf[rIndex] = 0;
	rIndex++;
	rIndex = (rIndex < LoopSz)?rIndex:0;
	if(dLen&0x80){		
		dLen <<=8;
		dLen += pBuf[rIndex];
		dLen = dLen&0x7FFF;
		pBuf[rIndex] = 0;
		rIndex++;
		rIndex = (rIndex < LoopSz)?rIndex:0;
	}
	//
	CopySz	= dLen;
	
	PartNum= LoopSz-rIndex; //  PartNum > 0
	if(CopySz > PartNum){
		for(i=0;i<PartNum;i++){
			// pRBuf[i] = pBuf[rIndex];
			pBuf[rIndex++] = 0;
		}
		rIndex = 0; 
		for(;i<CopySz;i++){
			//pRBuf[i] = pBuf[rIndex];
			pBuf[rIndex++] = 0;
		}
	}
	else{
		for(i=0;i<CopySz;i++){
			//pRBuf[i] = pBuf[rIndex];
			pBuf[rIndex++] = 0;
		}
	}
	rIndex = (rIndex < LoopSz)?rIndex:0;
	
	pObj->rIndex = rIndex;
	pObj->recvNum--;
	pObj->RWLock = 0;
    return CopySz;
}

#endif

